<?php

// +---------------------------------------------------------------------------+
// | This file is part of the Mojavi package.                                  |
// | Copyright (c) 2003 Sean Kerr.                                             |
// |                                                                           |
// | For the full copyright and license information, please view the COPYRIGHT |
// | file that was distributed with this source code. If the COPYRIGHT file is |
// | missing, please visit the Mojavi homepage: http://www.mojavi.org          |
// +---------------------------------------------------------------------------+

/**
 * Format URL's in the typical GET style.
 *
 * <br/><br/>
 *
 * Example: index.php?module=<i>Module</i>&action=<i>Action</i>
 *
 * @since 1.0
 * @type  int
 */
define('GET_FORMAT', 1);

/**
 * Format URL's in a search engine friendly style.
 *
 * <br/><br/>
 *
 * Example: index.php/module/<i>Module</i>/action/<i>Action</i>
 *
 * @since 1.0
 * @type  int
 */
define('PATH_FORMAT', 2);



// include dependencies
//require_once('Authorization.classes.php');
//require_once('Session.classes.php');
//require_once('User.classes.php');

/**
 * Controller dispatches requests to the proper action and controls application
 * flow.
 *
 * <br/><br/>
 *
 * <note>
 *     This class does not need to be included. It is part of the main library.
 * </note>
 *
 * @author  Sean Kerr
 * @package mojavi
 * @since   1.0
 */
class Controller 
{

    /**
     * A developer supplied authorization handler.
     *
     * @access private
     * @since  2.0
     * @type   AuthorizationHandler
     */
    var $authorizationHandler;

    /**
     * A developer supplied session handler.
     *
     * @access private
     * @since  2.0
     * @type   SessionHandler
     */
    var $sessionHandler;

    /**
     * A User instance.
     *
     * @access private
     * @since  1.0
     * @type   User
     */
    var $user;

    /**
     * Create a new Controller instance.
     *
     * <br/><br/>
     *
     * <note>
     *     This should never be called manually.
     * </note>
     *
     * @param string A content type.
     *
     * @access private
     * @since  1.0
     */
    function Controller ()
    {

        // init Controller objects
        $this->authorizationHandler =  NULL;
        $this->sessionHandler       =  NULL;
        $this->user                 =  NULL;

    }

    function start (&$usr, &$authH,&$sessH, $useSessions=TRUE)
    {
        // no user type has been set, use the default no privilege user
        $this->user = & $usr;
        $this->sessionHandler = & $sessH;
        $this->authorizationHandler = & $authH;
        
        if ($useSessions===TRUE)
        {

            if ($this->sessionHandler !== NULL)
            {

                session_set_save_handler(array(&$this->sessionHandler, 'open'),
                                         array(&$this->sessionHandler, 'close'),
                                         array(&$this->sessionHandler, 'read'),
                                         array(&$this->sessionHandler, 'write'),
                                         array(&$this->sessionHandler, 'destroy'),
                                         array(&$this->sessionHandler, 'gc'));

            }

            // set session container
            if($this->user->getContainer() == NULL)
	       {
	    	  $this->user->setContainer(new SessionContainer);
	       }

        }
        $this->user->load();
    }

     
    
    /**
     * Forward the request to an action.
     *
     * @param string A module name.
     * @param string An action name.
     *
     * @access public
     * @since  2.0
     */
    function forward ($modName, $actName)
    {

        if ($this->currentModule == $modName &&
            $this->currentAction == $actName)
        {

            $error = 'Recursive forward on module ' . $modName . ', action ' .
                     $actName;

            trigger_error($error, E_USER_ERROR);

            exit;

        }

        // execute module configuration, if it exists
        if (is_readable(MODULE_DIR . $modName . '/config.php'))
        {

            require_once(MODULE_DIR . $modName . '/config.php');

        }

        if ($this->actionExists($modName, $actName))
        {

            // create the action instance
            $action =& $this->getAction($modName, $actName);

        } else
        {

            // the requested action doesn't exist
            $action = NULL;

        }

        // track old module/action
        $oldAction = $this->currentAction;
        $oldModule = $this->currentModule;

        // add module and action to execution chain, and update current vars
        $this->execChain->addRequest($modName, $actName, $action);
        $this->updateCurrentVars($modName, $actName);

        if (!AVAILABLE)
        {

            // app is out-of-service
            $actName = UNAVAILABLE_ACTION;
            $modName = UNAVAILABLE_MODULE;

            if (!$this->actionExists($modName, $actName))
            {

                // cannot find unavailable module/action
                $error = 'Invalid configuration setting(s): ' .
                         'UNAVAILABLE_MODULE (' . $modName . ') or ' .
                         'UNAVAILABLE_ACTION (' . $actName . ')';

                trigger_error($error, E_USER_ERROR);

                exit;

            }

            // add another request since the site is unavailable
            $action =& $this->getAction($modName, $actName);

            $this->execChain->addRequest($modName, $actName, $action);
            $this->updateCurrentVars($modName, $actName);

        } else if ($action === NULL)
        {

            // requested action doesn't exist
            $actName = ERROR_404_ACTION;
            $modName = ERROR_404_MODULE;

            if (!$this->actionExists($modName, $actName))
            {

                // cannot find error 404 module/action
                $error = 'Invalid configuration setting(s): ' .
                         'ERROR_404_MODULE (' . $modName . ') or ' .
                         'ERROR_404_ACTION (' . $actName . ')';

                trigger_error($error, E_USER_ERROR);

                exit;

            }

            // add another request since the action is non-existent
            $action =& $this->getAction($modName, $actName);

            $this->execChain->addRequest($modName, $actName, $action);
            $this->updateCurrentVars($modName, $actName);

        }

        $filterChain =& new FilterChain;

        // map filters
        $this->mapGlobalFilters($filterChain);
        $this->mapModuleFilters($filterChain, $modName);

        // and last but not least, the main execution filter
        $filterChain->register(new ExecutionFilter);

        // execute filters
        $filterChain->execute($this, $this->request, $this->user);

        // update current vars
        $this->updateCurrentVars($oldModule, $oldAction);

    }
    function buildURL ($page,$protocol='http',$relative_path=NULL)
    {
        
        GLOBAL $HTTP_SERVER_VARS;
        GLOBAL $_SERVER;
        if ($relative_path==NULL){
            $path= substr($HTTP_SERVER_VARS["PHP_SELF"],0,strrpos($_SERVER["SCRIPT_NAME"],"/"));
        }
        else {
            $path =$relative_path;
        }
            
        $urlaction = $HTTP_SERVER_VARS["HTTP_HOST"] . "/".$path;    
        
        if (strcasecmp($protocol,"HTTPS")==0){
//            if (strtoupper($_SERVER['HTTPS'])!="ON"){
//                $error = 'Cannot apply HTTPS Protocol' ;
//                trigger_error($error, E_USER_ERROR);
//               exit;                
//            }
        }
        return $protocol."://".$urlaction."/".$page;
        
    }

    /**
     * Generate a formatted Mojavi URL.
     *
     * @param array An associative array of URL parameters.
     *
     * @return string A URL to a Mojavi resource.
     *
     * @access public
     * @since  1.0
     */
    function genURL ($params)
    {

        $url = SCRIPT_PATH;

        if (URL_FORMAT == PATH_FORMAT)
        {

            $divider  = '/';
            $equals   = '/';
            $url     .= '/';

        } else
        {

            // use an else and not a condition to cover any unknown formats
            $divider  = '&';
            $equals   = '=';
            $url     .= '?';

        }

        $keys  = array_keys($params);
        $count = sizeof($keys);

        for ($i = 0; $i < $count; $i++)
        {

            if ($i > 0)
            {

                $url .= $divider;

            }

            $url .= urlencode($keys[$i]) . $equals .
                    urlencode($params[$keys[$i]]);

        }

        return $url;

    }

    /**
     * Retrieve the developer supplied authorization handler.
     *
     * @return AuthorizationHandler An AuthorizationHandler instance, if an
     *                              authorization handler has been set,
     *                              otherwise <b>NULL</b>.
     *
     * @access public
     * @since  2.0
     */
    function & getAuthorizationHandler ()
    {

        return $this->authorizationHandler;

    }

    /**
     * Retrieve an absolute web path to the public controller file.
     *
     * @param string A module name.
     * @param string An action name.
     *
     * @return string An absolute web path representing the controller file,
     *                which also includes module and action names.
     *
     * @access public
     * @since  1.0
     */
    function getControllerPath ($modName = NULL, $actName = NULL)
    {

        $path = SCRIPT_PATH;

        if ($modName != NULL)
        {

            $path .= (URL_FORMAT == GET_FORMAT)
                     ? '?' . MODULE_ACCESSOR . '=' . $modName
                     : '/' . MODULE_ACCESSOR . '/' . $modName;

        }

        if ($actName != NULL)
        {

            $sep = ($path == SCRIPT_PATH) ? '?' : '&';

            $path .= (URL_FORMAT == GET_FORMAT)
                     ? $sep . ACTION_ACCESSOR . '=' . $actName
                     : '/' . ACTION_ACCESSOR . '/' . $actName;

        }

        return $path;

    }

    /**
     * Retrieve the single instance of Controller.
     *
     * @param string A user supplied content type.
     *
     * @return Controller A Controller instance.
     *
     * @access public
     * @since  2.0
     */
    function & getInstance ()
    {
        // return Singleton::getSingleton("Controller");
        
        static $instance;

        if ($instance === NULL)
        {
            // can't use reference with static data
            $instance = new Controller();

        }

        return $instance;
    }

    /**
     * Retrieve the developer supplied session handler.
     *
     * @return SessionHandler A SessionHandler instance, if a session handler
     *                        has been set, otherwise <b>NULL</b>.
     *
     * @access public
     * @since  2.0
     */
    function & getSessionHandler ()
    {

        return $this->sessionHandler;

    }

    /**
     * Retrieve the currently requesting user.
     *
     * @return User A User instance.
     *
     * @access public
     * @since  1.0
     */
    function & getUser ()
    {

        return $this->user;

    }

    /**
     * Parse and retrieve all PATH/REQUEST parameters.
     *
     * @return array An associative array of parameters.
     *
     * @access private
     * @since  1.0
     */
    function & parseParameters ()
    {

        $values = array();

        // load GET params into $values array
        $values = array_merge($values, $_GET);

        // grab PATH_INFO parameters
        if (URL_FORMAT == PATH_FORMAT                                 &&
            ((PATH_INFO_ARRAY == 1 && isset($_SERVER[PATH_INFO_KEY])) ||
             (PATH_INFO_ARRAY == 2 && isset($_ENV[PATH_INFO_KEY]))))
        {

            if (PATH_INFO_ARRAY == 1)
            {

                $array =& $_SERVER;

            } else
            {

                $array =& $_ENV;
            }

            $getArray = explode('/', trim($array[PATH_INFO_KEY], '/'));
            $count    = sizeof($getArray);

            for ($i = 0; $i < $count; $i++)
            {

                // see if there's a value associated with this parameter,
                // if not we're done with path data
                if ($count > ($i + 1))
                {

                    $values[$getArray[$i]] =& $getArray[++$i];

                }

            }

        }

        // load POST params into $values array
        $values = array_merge($values, $_POST);

        // strip slashes from values if magic_quotes_gpc is on
        if (ini_get('magic_quotes_gpc') == 1 && sizeof($values) > 0)
        {

            $this->stripSlashes($values);

        }

        return $values;

    }

    /**
     * Redirect the request to another location.
     *
     * @param string A URL.
     *
     * @access public
     * @since  2.0
     */
    function redirect ($url)
    {

        header('Location: ' . $url);

    }

    /**
     * Set the developer supplied authorization handler.
     *
     * @param Authorizationhandler An AuthorizationHandler instance.
     *
     * @access public
     * @since  2.0
     */
    function setAuthorizationHandler (&$handler)
    {

        $this->authorizationHandler =& $handler;

    }

    /**
     * Set the session handler.
     *
     * @param SessionHandler A SessionHandler instance.
     *
     * @access public
     * @since  2.0
     */
    function setSessionHandler (&$handler)
    {

        $this->sessionHandler =& $handler;

    }

    /**
     * Set the user type.
     *
     * @param User A User instance.
     *
     * @access public
     * @since  2.0
     */
    function setUser (&$user)
    {

        $this->user =& $user;

    }

    /**
     * Strip slashes from all parameter values.
     *
     * @param array An associative array of parameters.
     *
     * @access private
     * @since  1.0
     */
    function stripSlashes (&$params)
    {

        $keys  = array_keys($params);
        $count = sizeof($keys);

        for ($i = 0; $i < $count; $i++)
        {

            $value =& $params[$keys[$i]];

            if (is_array($value))
            {

                // traverse through the array and strip some more crap, oops
                // i mean magic_quotes_gpc leftovers
                $this->stripSlashes($value);

            } else
            {

                // bug fixed by wolfpakz
                $value = stripslashes($value);

            }

        }

    }
  /**
     * Store Controller data.
     *
     *
     * @access public
     * @since  1.0
     */
    function store ()
    {
        
     //   $this->user->store();  
/*      
        $className=__CLASS__;
        $inst_name = "_INSTANCE_" . strtoupper($className);
        if (isset($_SESSION))
        {   
           $_SESSION[$inst_name] = & $this; 
        }else{
            echo "GLOBAl Store <BR>";
           $GLOBALS[$inst_name] =  & $this; 
        }
        */
    }    
}

// set the display error status
//ini_set('display_errors', DISPLAY_ERRORS);

?>
